package com.jusda.message.producer;

import com.alibaba.fastjson.JSON;
import com.jusda.message.entity.UserScore;
import com.jusda.message.producer.strategy.ProducerStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author yiyi
 * @Date 2022/3/14-下午4:37
 * @Description:
 */
@Component
@Slf4j
public class SyncProducerStrategy implements ProducerStrategy {

    @Autowired
    private DefaultMQProducer defaultMQProducer;

    /**
     * 同步发送消息
     * 单条发送消息,使用分区选择器，保证消息都发送到每一个分区中，在消息生产端保证消息的有序性
     *
     * @param data
     * @throws MQClientException
     */
    public void sendMessage(UserScore data) throws MQClientException {
        try {
            Message message = new Message("rocketmq-service", JSON.toJSONBytes(data));
            Integer orderId = 100;
            SendResult send = defaultMQProducer.send(message, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object bizId) {
                    //bizId == orderId,可以保证是每个订单进入同一个队列
                    Integer id = (Integer) bizId;
                    int index = id % mqs.size();
                    return mqs.get(index);
                }
            }, orderId);
            validSendResult(send);
        } catch (Exception e) {
            throw new MQClientException("消息发送失败", e);
        }
    }

    @Override
    public void batchSendMessage(List<UserScore> data) throws MQClientException {
        batchSendMsg(data);
    }

    /**
     * 批量发送消息
     *
     * @param data
     */
    public void batchSendMsg(List<UserScore> data) {
        try {
            validSendResult(defaultMQProducer.send(buildMsg(data)));
        } catch (Exception e) {
            log.error("消息发送失败！", e);
            e.printStackTrace();
        }
    }

    /**
     * 构建消息
     *
     * @param data
     * @return
     */
    private List<Message> buildMsg(@NotNull List<UserScore> data) {

        return data.stream().map(e -> {
            if (e.getId() % 2 == 0) {
                return new Message(defaultMQProducer.getProducerGroup(), "a", JSON.toJSONBytes(e));
            } else {
                return new Message(defaultMQProducer.getProducerGroup(), "b", JSON.toJSONBytes(e));
            }
        }).collect(Collectors.toList());
    }

    /**
     * 验证发送结果
     *
     * @param sendResult
     */
    private void validSendResult(SendResult sendResult) {
        if (Objects.equals(sendResult.getSendStatus(), SendStatus.SEND_OK)) {
            log.info("消息发送成功！{}", new Date());
        } else {
            log.warn("消息发送失败！发送结果:{},msgId:{}", sendResult.getSendStatus(), sendResult.getMsgId());
        }
    }
}
